package com.sentiment.report;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.bson.types.ObjectId;

import com.sentiment.config.Config;
import com.sentiment.config.ConfigDb;
import com.sentiment.crawler.BaiduNewsCrawler;
import com.sentiment.database.bean.CrawlNews;
import com.sentiment.database.bean.DailyReport;
import com.sentiment.database.bean.HotspotReport;
import com.sentiment.database.codec.DailyReportCodec;
import com.sentiment.database.codec.HotspotReportCodec;
import com.sentiment.database.dbUtil.DbCodecDriver;
import com.sentiment.tools.Format;
import com.sentiment.tools.Generator;

public class HotReportUtils {
	private DbCodecDriver<HotspotReport> driver = new DbCodecDriver<HotspotReport>();
	private static final Object LOCK = new Object();
	public static final List<WatchHotReport> list = new ArrayList<WatchHotReport>();
	// 未发布（未监测）的热点舆情报告
	public static final int UN_WATCHED = 1;
	// 已发布的热点舆情报告（监测完成）
	public static final int PUBLISHED = 3;
	// 正在监测的热点舆情报告
	public static final int WATCHING = 2;
	// 无用的热点舆情报告
	public static final int UN_USED = 9;
	// 7天
	public static final long DATE_APPEND = 7 * 24 * 60 * 60 * 1000;

	private void open() {
		driver.openConnection(ConfigDb.sentimentDb, HotspotReport.class, HotspotReportCodec.class);
	}

	private void close() {
		driver.closeConnection();
	}

	private HotspotReport toHotspotReport(DailyReport dr) {
		String beginDate = dr.getDate();
		Calendar calendar = Calendar.getInstance();
		calendar.setTimeInMillis(Format.string2Date(beginDate, 6).getTime() + DATE_APPEND);
		String endDate = Format.date2String(calendar.getTime(), 3);

		HotspotReport report = new HotspotReport(beginDate, endDate, dr.getTitle(), dr.getText(),
				dr.getWeiboOpinion_id(), dr.getForumOpinion_id());

		Map<String, Integer> commentMap = new HashMap<String, Integer>();
		Map<String, Double> sentimentMap = new HashMap<String, Double>();
		sentimentMap.put(Format.date2String(new Date(), 6), dr.getSentiment());
		Map<String, Integer> reprintMap = new HashMap<String, Integer>();

		report.setCommentRatio(commentMap);
		report.setSentimentRatio(sentimentMap);
		report.setReprintRatio(reprintMap);

		report.setStatus(UN_WATCHED);
		report.setWatchCount(7);

		return report;
	}

	/**
	 * 将一个每日报告的id传入，改每日报告为热点报告
	 * 
	 * @param id
	 */
	public void watchHotReport(ObjectId id) {
		// 每日报告的数据库查询
		DbCodecDriver<DailyReport> driver1 = new DbCodecDriver<DailyReport>();
		driver1.openConnection(ConfigDb.sentimentDb, DailyReport.class, DailyReportCodec.class);
		DailyReport rp = new DailyReport();
		rp.set_id(id);
		rp = driver1.query(rp);
		driver1.closeConnection();

		// rp为id对应的每日报告，将其转换成热点舆情报告对象
		HotspotReport hotReport = toHotspotReport(rp);
		// 将id作为待监测的线程的记录保存在list中
		// 热点舆情报告插入到数据库中
		open();
		driver.insert(hotReport);
		list.add(new WatchHotReport(hotReport.get_id()));
		close();
	}

	/**
	 * 执行所有在list中的线程一次
	 */
	public void watchExecute() {
		ExecutorService exec = Executors.newCachedThreadPool();
		if (!list.isEmpty()) {
			for (WatchHotReport task : list) {
				exec.execute(task);
			}
		} else {
			open();
			List<HotspotReport> reports = driver.queryMany(new HotspotReport(HotReportUtils.WATCHING));
			close();
			for (HotspotReport report : reports) {
				list.add(new WatchHotReport(report.get_id()));
			}
			if (!list.isEmpty()) {
				for (WatchHotReport task : list) {
					exec.execute(task);
				}
			}
		}
	}

	public void clearList() {
		list.clear();
	}

	class WatchHotReport implements Runnable {
		private ObjectId report_id;
		private int watchCount;

		public WatchHotReport(ObjectId report_id) {
			// TODO Auto-generated constructor stub
			this.report_id = report_id;
		}

		@Override
		public void run() {
			open();
			HotspotReport report = driver.query(new HotspotReport(report_id));
			close();
			watchCount = report.getWatchCount();
			// TODO Auto-generated method stub
			if (watchCount > 0) {
				synchronized (LOCK) {
					watchOnce(report);
				}
			} else {
				report.setStatus(PUBLISHED);
				synchronized (list) {
					list.remove(this);
				}
			}
		}

		public synchronized void watchOnce(HotspotReport report) {
			BaiduNewsCrawler bnc = new BaiduNewsCrawler(Config.crawlerDataPath);
			bnc.getSearch(report.getTitle(), 1);
			List<CrawlNews> list = bnc.getNewsList();
			Iterator<CrawlNews> it = list.iterator();
			int comment = 0;
			double sentiment = 0.0;
			// 随机生成的测试数据
			if (!Config.useNlp) {
				sentiment = Generator.genenrateDouble(0, 1);
			} else {

			}
			int reprint = 0;
			while (it.hasNext()) {
				CrawlNews n = it.next();
				comment += n.getComment() == null ? 0 : n.getComment();
				reprint += n.getReprint() == null ? 0 : n.getReprint();
			}
			report.getCommentRatio().put(Format.date2String(new Date(), 6), comment);
			report.getReprintRatio().put(Format.date2String(new Date(), 6), reprint);
			report.getSentimentRatio().put(Format.date2String(new Date(), 6), sentiment);
			watchCount--;
			report.setWatchCount(watchCount);
			if (watchCount == 0) {
				report.setStatus(PUBLISHED);
			}
			updateReport(report);
		}

		public synchronized void updateReport(HotspotReport report) {
			HotspotReport update = new HotspotReport();
			update.setUpdate("$set", report);
			HotspotReport target = new HotspotReport(report_id);

			open();
			driver.update(target, update);
			close();
		}
	}

	/**
	 * 根据id查找热点舆情报告
	 * 
	 * @param id
	 * @return
	 */
	public HotspotReport findHotspotReport(ObjectId id) {
		open();
		HotspotReport report = driver.query(new HotspotReport(id));
		close();
		return report;
	}

	/**
	 * 获取到位于某一状态的所有热点舆情报告
	 * 
	 * @param status
	 * @return
	 */
	public List<HotspotReport> findHotspotReport(Integer status) {
		open();
		List<HotspotReport> report = driver.queryMany(new HotspotReport(status));
		close();
		return report;
	}

	/**
	 * 根据传入的id更新一个热点舆情报告的发布状态信息 修改未监测为已监测，已监测为未监测，并返回
	 * 
	 * @param id
	 * @return
	 */
	public Integer updateStatus(ObjectId id) {
		open();
		HotspotReport target = new HotspotReport(id);
		HotspotReport report = driver.query(target);
		// 需要创建一个update的文档，对应$set的值为更新的文档
		HotspotReport update = new HotspotReport();
		int status = report.getStatus();
		if (status == 1) {
			report.setStatus(2);
		} else {
			report.setStatus(1);
		}
		update.setUpdate("$set", report);

		driver.update(target, update);

		close();
		return report.getStatus();
	}
	
	/**
	 * 根据传入的页码和每页显示的数量返回每日舆情报告的列表
	 * 
	 * @param pagenum
	 *            页码
	 * @param pageview
	 *            每页显示数
	 * @return
	 */
	public List<HotspotReport> findHotspotReport(int pagenum, int pageview) {
		open();
		List<HotspotReport> list = driver.getPage(pagenum, pageview);
		close();
		return list;
	}
}
